﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;

//public struct ABCube
//{
//	public GameObject go;
//	public AABB aabb;
//	public float lv;
//}

public class GameScene : MonoBehaviour {
	public GameObject prefab;
	public Material redMat;
	public Material defaltMat;
	public bool UseSpace;

	private List<AABB> abCubeList = new List<AABB>(); //碰撞体列表
	private List<List<AABB>> spaceList = new List<List<AABB>>(); //划分空间列表
	private List<AABB>[] tempSpace;
	private float border = 50f; //边界大小
	private float unit_space = 10f; //边界单位大小
	private int line = 0;
	int num = 2000; //碰撞数量
	int size = 5; //缩放最大值
	// Use this for initialization
	void Start () {
		
		for (int i = 0; i < num; i++)
        {
			GameObject go = Instantiate(prefab, gameObject.transform);
			go.transform.position = new Vector3(UnityEngine.Random.RandomRange(-border, border), UnityEngine.Random.RandomRange(-border, border), UnityEngine.Random.RandomRange(-border, border));
			go.transform.localScale = new Vector3(UnityEngine.Random.RandomRange(1, size), UnityEngine.Random.RandomRange(1, size), UnityEngine.Random.RandomRange(1, size));
			AABB aabb = new AABB(go, go.transform.position, go.transform.localScale.x, go.transform.localScale.y, go.transform.localScale.z, UnityEngine.Random.RandomRange(0.1f, 0.5f));
			abCubeList.Add(aabb);
		}

		line = Convert.ToInt32(Math.Ceiling(this.border * 2 / this.unit_space));
		Debug.LogError(line);
	}
	
	
	// Update is called once per frame
	void Update () {
		//spaceList = new List<List<AABB>>();
		tempSpace = new List<AABB>[line * line];
		for (int i = 0; i < abCubeList.Count; i++)
		{
			AABB abCube = abCubeList[i];
			GameObject go = abCube.go;
			go.GetComponent<MeshRenderer>().material = defaltMat;
			Vector3 pos = go.transform.position;
			if (i < abCubeList.Count / 2)
			{
				if (pos.y >= border)
				{
					abCube.lv = -1f * abCube.lv;
				}
				if (pos.y <= -border)
				{
					abCube.lv = -1f * abCube.lv;
				}
				go.transform.position = new Vector3(pos.x, pos.y + abCube.lv, pos.z);
			}
			else
			{
				if (pos.x >= border)
				{
					abCube.lv = -1f * abCube.lv;
				}
				if (pos.x <= -border)
				{
					abCube.lv = -1f * abCube.lv;
				}
				go.transform.position = new Vector3(pos.x + abCube.lv, pos.y, pos.z);
			}

			abCube.UpdatePos(go.transform.position);

            if (UseSpace)
            {
				Vector3 minV = abCube.GetMinVec();
				Vector3 maxV = abCube.GetMaxVec();
				float tempMinX = (minV.x + this.border) < 0 ? 1 : minV.x + this.border;
				int indexMinX = Convert.ToInt32(Math.Ceiling(tempMinX / this.unit_space)) - 1;
				float tempMinY = (minV.y + this.border) < 0 ? 1 : minV.y + this.border;
				int indexMinY = Convert.ToInt32(Math.Ceiling(tempMinY / this.unit_space)) - 1;

				float tempMaxX = (maxV.x + this.border) > this.border * 2 ? this.border * 2 : maxV.x + this.border;
				int indexMaxX = Convert.ToInt32(Math.Ceiling(tempMaxX / this.unit_space)) - 1;
				float tempMaxY = (maxV.y + this.border) > this.border * 2 ? this.border * 2 : maxV.y + this.border;
				int indexMaxY = Convert.ToInt32(Math.Ceiling(tempMaxY / this.unit_space)) - 1;

				if (tempSpace[indexMinX * line + indexMinY] == null)
				{
					tempSpace[indexMinX * line + indexMinY] = new List<AABB>();
				}
				tempSpace[indexMinX * line + indexMinY].Add(abCube);

				if (!(indexMinX == indexMaxX && indexMinY == indexMaxY))
				{
					if (tempSpace[indexMaxX * line + indexMaxY] == null)
					{
						tempSpace[indexMaxX * line + indexMaxY] = new List<AABB>();
					}
					tempSpace[indexMaxX * line + indexMaxY].Add(abCube);
				}
			}
			
        }

		if(UseSpace)
        {
			for (int i = 0; i < tempSpace.Length; i++)
			{
				if (tempSpace[i] != null && tempSpace[i].Count > 1)
				{
					for (int j = 0; j < tempSpace[i].Count - 1; j++)
					{
						AABB abCube1 = tempSpace[i][j];
						GameObject go1 = abCube1.go;

						for (int k = j + 1; k < tempSpace[i].Count; k++)
						{
							AABB abCube2 = tempSpace[i][k];
							GameObject go2 = abCube2.go;

							bool flg = abCube2.Check(abCube1);

							if (flg)
							{
								go1.GetComponent<MeshRenderer>().material = redMat;
								go2.GetComponent<MeshRenderer>().material = redMat;
								break;
							}
						}
					}
				}
			}
        }
        else
        {
			for (int i = 0; i < abCubeList.Count - 1; i++)
			{
				AABB abCube1 = abCubeList[i];
				GameObject go1 = abCube1.go;
				for (int j = i + 1; j < abCubeList.Count; j++)
				{
					AABB abCube2 = abCubeList[j];
					GameObject go2 = abCube2.go;

					bool flg = abCube2.Check(abCube1);
					//Debug.LogError(Convert.ToString(flg));
					//Debug.LogError(Convert.ToString(i) + " " + Convert.ToString(j));

					if (flg)
					{
						go1.GetComponent<MeshRenderer>().material = redMat;
						go2.GetComponent<MeshRenderer>().material = redMat;
						break;
					}
				}
			}
		}
    }
}
